/****************************************************************************\
*                                                                            *
*  Copyright 2008 The CAnt2 Project (http://code.google.com/p/cant2)         *
*                                                                            *
*  Licensed under the Apache License, Version 2.0 (the "License");           *
*  you may not use this file except in compliance with the License.          *
*  You may obtain a copy of the License at                                   *
*                                                                            *
*      http://www.apache.org/licenses/LICENSE-2.0                            *
*                                                                            *
*  Unless required by applicable law or agreed to in writing, software       *
*  distributed under the License is distributed on an "AS IS" BASIS,         *
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
*  See the License for the specific language governing permissions and       *
*  limitations under the License.                                            *
*                                                                            *
\****************************************************************************/

#include "UnitTest.h"
#include "CAnt2/src/core/MiniXmlDOM.h"
#include "CAnt2/src/core/StringPool.h"

namespace {

    SUITE ( MiniXmlDOMTests )
    {
        TEST ( EmptyDocument )
        {
            MiniXmlDOM::DocumentFactory df;

            df.EndOfFile();

            MiniXmlDOM::Document doc;
            df.Get ( doc );

            CHECK ( doc.firstChild.IsEmpty() );
        }

        TEST ( TrivialDocument )
        {
            MiniXmlDOM::DocumentFactory df;

            df.ElementBegin ( L"abc" );
            df.ElementEndAttributes ( L"abc" );
            df.ElementEnd ( L"abc" );
            df.EndOfFile();

            MiniXmlDOM::Document doc;
            df.Get ( doc );

            CHECK ( doc.firstChild->name.handle == StringPool::Insert ( L"abc" ) );
            CHECK ( doc.firstChild->firstAttribute.IsEmpty() );
            CHECK ( doc.firstChild->firstChild.IsEmpty() );
            CHECK ( doc.firstChild->nextSibling.IsEmpty() );
        }

        TEST ( NotSoTrivialDocument )
        {
            MiniXmlDOM::DocumentFactory df;

            CHECK_NOTHROW ( df.ElementBegin ( L"abc" ) );
            CHECK_NOTHROW ( df.Attribute ( L"a", L"123" ) );
            CHECK_NOTHROW ( df.Attribute ( L"b", L"" ) );
            CHECK_NOTHROW ( df.Attribute ( L"c", L"Fourscore and seven years ago" ) );
            CHECK_NOTHROW ( df.ElementEndAttributes ( L"abc" ) );
            CHECK_NOTHROW ( df.ElementBegin ( L"def1" ) );
            CHECK_NOTHROW ( df.Attribute ( L"d", L"456" ) );
            CHECK_NOTHROW ( df.Attribute ( L"ef", L"d;e;f" ) );
            CHECK_NOTHROW ( df.ElementEndAttributes ( L"def1" ) );
            CHECK_NOTHROW ( df.ElementBegin ( L"ghi" ) );
            CHECK_NOTHROW ( df.Attribute ( L"ghi", L"" ) );
            CHECK_NOTHROW ( df.ElementEndAttributes ( L"ghi" ) );
            CHECK_NOTHROW ( df.ElementEnd ( L"ghi" ) );
            CHECK_NOTHROW ( df.ElementEnd ( L"def1" ) );
            CHECK_NOTHROW ( df.ElementBegin ( L"def2" ) );
            CHECK_NOTHROW ( df.Attribute ( L"d", L"789" ) );
            CHECK_NOTHROW ( df.Attribute ( L"e", L"" ) );
            CHECK_NOTHROW ( df.Attribute ( L"f", L"some/file/**/pattern/here*" ) );
            CHECK_NOTHROW ( df.ElementEndAttributes ( L"def2" ) );
            CHECK_NOTHROW ( df.ElementEnd ( L"def2" ) );
            CHECK_NOTHROW ( df.ElementBegin ( L"def3" ) );
            CHECK_NOTHROW ( df.ElementEndAttributes ( L"def3" ) );
            CHECK_NOTHROW ( df.ElementEnd ( L"def3" ) );
            CHECK_NOTHROW ( df.ElementEnd ( L"abc" ) );
            df.EndOfFile();

            MiniXmlDOM::Document doc;
            df.Get ( doc );

            const MiniXmlDOM::Attribute* attr;
            const MiniXmlDOM::Element* elem;

            elem = doc.firstChild.Get();
            CHECK ( elem->nextSibling.IsEmpty() );
            CHECK ( elem->name.handle == StringPool::Insert ( L"abc" ) );
            attr = elem->firstAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"a" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"123" ) );
            attr = attr->nextAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"b" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"" ) );
            attr = attr->nextAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"c" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"Fourscore and seven years ago" ) );
            CHECK ( attr->nextAttribute.IsEmpty() );

            elem = elem->firstChild.Get();
            CHECK ( elem->name.handle == StringPool::Insert ( L"def1" ) );
            attr = elem->firstAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"d" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"456" ) );
            attr = attr->nextAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"ef" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"d;e;f" ) );
            CHECK ( attr->nextAttribute.IsEmpty() );

            elem = elem->firstChild.Get();
            CHECK ( elem->name.handle == StringPool::Insert ( L"ghi" ) );
            attr = elem->firstAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"ghi" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"" ) );
            CHECK ( attr->nextAttribute.IsEmpty() );
            CHECK ( elem->firstChild.IsEmpty() );
            CHECK ( elem->nextSibling.IsEmpty() );

            elem = doc.firstChild->firstChild->nextSibling.Get();
            CHECK ( elem->name.handle == StringPool::Insert ( L"def2" ) );
            attr = elem->firstAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"d" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"789" ) );
            attr = attr->nextAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"e" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"" ) );
            attr = attr->nextAttribute.Get();
            CHECK ( attr->name.handle  == StringPool::Insert ( L"f" ) );
            CHECK ( attr->value.handle == StringPool::Insert ( L"some/file/**/pattern/here*" ) );
            CHECK ( attr->nextAttribute.IsEmpty() );

            elem = elem->nextSibling.Get();
            CHECK ( elem->name.handle == StringPool::Insert ( L"def3" ) );
            CHECK ( elem->firstAttribute.IsEmpty() );
            CHECK ( elem->firstChild.IsEmpty() );
            CHECK ( elem->nextSibling.IsEmpty() );
        }
    }
}

